<?php

namespace App\Services;
use App\Exceptions\BaseException;

// 1. 资源及配置加载
# 加载 SDK 初始化文件
class BaofupayService
{
    protected $Version;
    protected $Member_Id;
    protected $Terminal_Id;
    protected $KEY_PWD;
    protected $PFX_FILE_PATH;
    protected $CER_FILE_PATH;
    protected $POST_URL;
    protected $dgtl_envlp;
    public function __construct(){

        $ServicesPath = $_SERVER['DOCUMENT_ROOT']?$_SERVER['DOCUMENT_ROOT']:'D:\phpstudy_pro\WWW\doulaizuba\public';
        $KeyFolder = $ServicesPath."/CerFile/";	//证书路径
        $this->Version = "4.0.0.0";//版本号
        $this->Member_Id = "1273867";	//商户号
        $this->Terminal_Id = "81920";	//终端号
        $this->KEY_PWD = "123456";	//商户私钥证书密码
        $this->PFX_FILE_PATH = $KeyFolder."bfkey.pfx";      //注意证书路径是否存在
        $this->CER_FILE_PATH = $KeyFolder."baofu.cer";//注意证书路径是否存在
        $this->AesKey = "4f66405c4f66406a";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $this->dgtl_envlp = "01|".$this->AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]
        // $this->POST_URL = "https://vgw.baofoo.com/cutpayment/protocol/backTransRequest";  //测试环境请求地址

        $this->POST_URL = "https://public.baofoo.com/cutpayment/protocol/backTransRequest";  //测试环境请求地址
    }
    /**
     * 记录日志
     * @param $message
     * @param array $request
     * @param array $response
     */
    public static function requestLog($message,$request=[],$response=[]){
        $content = [
            'request'=>is_object($request) ? object_array($request) : $request,
            'response'=>is_object($response) ? object_array($response) : $response,
        ];
        \Illuminate\Support\Facades\log::debug($message,$content);
    }
    /**
     * 预绑卡
     * @param $params
     * @return void
     */
    public  function readySign($params=[])
    {
        $AesKey=$this->AesKey;
        $dgtl_envlp = $this->dgtl_envlp;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]
//        //$this->EchoFormat("密码dgtl_envlp：".$this->dgtl_envlp);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
//        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);
        $Cardinfo = "{$params['card_no']}|{$params['card_holder_name']}|{$params['cert_no']}|{$params['mobile_no']}||";//账户信息[银行卡号|持卡人姓名|证件号|手机号|银行卡安全码|银行卡有效期]
//        //$this->EchoFormat("卡信息：".$Cardinfo.",长度：".strlen($Cardinfo));
        $CardinfoAES = $this->AesEncrypt(base64_encode($Cardinfo), $AesKey);//先BASE64后进行AES加密

        //$this->EchoFormat("AES结果:".$Cardinfo);
        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "01";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["user_id"]= $params['uid'];//用户在商户平台唯一ID
        $DateArry["card_type"]="101";//卡类型  101	借记卡，102 信用卡
        $DateArry["id_card_type"]= "01";//证件类型
        $DateArry["acc_info"]=$CardinfoAES;

        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign =  $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
//        $this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

//        var_dump($DateArry);
        $PostString  =   $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);
        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
//        $this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature =  $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
//        $this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if( !$this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }
        self::requestLog("预绑卡",$DateArry,$RSignArray);
        if($RSignArray["resp_code"] == "S"){
            if(!array_key_exists("dgtl_envlp",$RSignArray)){
                throw new BaseException("缺少dgtl_envlp参数！");
            }
            //$this->EchoFormat("dgtl_envlp:".$RSignArray["dgtl_envlp"]);
            $RDgtlEnvlp = $this->decryptByPFXFile($RSignArray["dgtl_envlp"], $this->PFX_FILE_PATH,$this->KEY_PWD);
            //$this->EchoFormat("返回数字信封：".$RDgtlEnvlp);
            $RAesKey=  CommonService::getAesKey($RDgtlEnvlp);//获取返回的AESkey
            //$this->EchoFormat("返回的AESkey:".$RAesKey);

//            var_dump($RSignArray);
            $UniqueCode=  base64_decode($this->AesDecrypt($RSignArray["unique_code"], $RAesKey));
            //return $RSignArray;
            //$this->EchoFormat("唯一码:".$UniqueCode);
            return $UniqueCode;
        }else{
            throw new BaseException($RSignArray['biz_resp_msg']);
        }
    }

    /**
     * 确认绑卡（协议支付）
     * @param $params
     * @return void
     */
    public function confirmSign($params=[]){

        $AesKey=$this->AesKey;
        $dgtl_envlp = $this->dgtl_envlp;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]

        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
        $dgtl_envlp = self::encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);

        $SMSStr=$params['verificationCode'];//短信验证码，测试环境随机6位数;生产环境验证码预绑卡成功后发到用户手机。确认绑卡时回传。
        $UniqueCode = "{$params['msgId']}|".$SMSStr;//预签约唯一码(预绑卡返回的值)[格式：预签约唯一码|短信验证码]
        //$this->EchoFormat("UniqueCode：".$UniqueCode.",长度：".strlen($UniqueCode));
        $UniqueCodeAES = self::AesEncrypt(base64_encode($UniqueCode), $AesKey);//先BASE64后进行AES加密
        //$this->EchoFormat("AES结果:".$UniqueCodeAES);

        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "02";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["unique_code"]= $UniqueCodeAES;//预签约唯一码

        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if(!$this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){

            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        self::requestLog("确认绑卡（协议支付）",$DateArry,$RSignArray);

        if($RSignArray["resp_code"] == "S"){
            if(!array_key_exists("dgtl_envlp",$RSignArray)){
                throw new BaseException("缺少dgtl_envlp参数！");
            }
            //$this->EchoFormat("dgtl_envlp:".$RSignArray["dgtl_envlp"]);
            $RDgtlEnvlp = $this->decryptByPFXFile($RSignArray["dgtl_envlp"], $this->PFX_FILE_PATH,$this->KEY_PWD);
            //$this->EchoFormat("返回数字信封：".$RDgtlEnvlp);
            $RAesKey=  CommonService::getAesKey($RDgtlEnvlp);//获取返回的AESkey
            //$this->EchoFormat("返回的AESkey:".$RAesKey);

            $UniqueCode=  base64_decode($this->AesDecrypt($RSignArray["protocol_no"], $RAesKey));

            return $UniqueCode;
            //$this->EchoFormat("签约协议号:".$UniqueCode);
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
            throw new BaseException("处理中！");
        }else if($RSignArray["resp_code"] =="F"){
            //$this->EchoFormat("失败！");
            throw new BaseException("签约失败！");
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }


    }

    /**
     * 查询绑卡接口
     * @return void
     */
    public function queryBind(){

        //$this->EchoFormat("==========================");
        //$this->EchoFormat("绑卡查询 测试实例");
        //$this->EchoFormat("==========================");
        $AesKey = "4f66405c4f66405c";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $dgtl_envlp = "01|".$AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]

        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);
        $AccNo = "6222020111122220000";//银行卡号
        //$this->EchoFormat("银行卡号：".$AccNo);
        $AccNoAES = $this->AesEncrypt(base64_encode($AccNo), $AesKey);//先BASE64后进行AES加密

        //$this->EchoFormat("AES结果:".$AccNoAES);
        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "03";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["user_id"]= "";//用户在商户平台唯一ID
        $DateArry["acc_no"]=$AccNoAES;//银行卡号密文[与user_id必须其中一个有值]

        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if($this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            //$this->EchoFormat("验签:Yes");//验签成功
        }  else {
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        if($RSignArray["resp_code"] == "S"){
            if(!array_key_exists("dgtl_envlp",$RSignArray)){
                throw new BaseException("缺少dgtl_envlp参数！");
            }
            //$this->EchoFormat("dgtl_envlp:".$RSignArray["dgtl_envlp"]);
            $RDgtlEnvlp = $this->decryptByPFXFile($RSignArray["dgtl_envlp"], $this->PFX_FILE_PATH,$this->KEY_PWD);
            //$this->EchoFormat("返回数字信封：".$RDgtlEnvlp);
            $RAesKey=  CommonService::getAesKey($RDgtlEnvlp);//获取返回的AESkey
            //$this->EchoFormat("返回的AESkey:".$RAesKey);

            $UniqueCode=  base64_decode($this->AesDecrypt($RSignArray["protocols"], $RAesKey));
            //$this->EchoFormat("签约协议号:".$UniqueCode);
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
        }else if($RSignArray["resp_code"] =="F"){
            //$this->EchoFormat("失败！");
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }

    }

    /**
     * 解除绑卡接口
     * @return void
     */
    public function ABolishBind(){

        //$this->EchoFormat("==========================");
        //$this->EchoFormat("解绑接口 测试实例");
        //$this->EchoFormat("==========================");
        $AesKey = "4f66405c4f66405c";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $dgtl_envlp = "01|".$AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]

        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);
        $ProtocolNo = "1202306281451538580008246542";//签约协议号（确认绑卡返回）
        //$this->EchoFormat("签约协议号：".$ProtocolNo);
        $ProtocolNoAES = $this->AesEncrypt(base64_encode($ProtocolNo), $AesKey);//先BASE64后进行AES加密

        //$this->EchoFormat("签约协议号AES结果:".$ProtocolNoAES);
        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "04";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["user_id"]= "";//用户在商户平台唯一ID
        $DateArry["protocol_no"]=$ProtocolNoAES;//签约协议号（密文）


        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if($this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            //$this->EchoFormat("验签:Yes");//验签成功
        }  else {
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        if($RSignArray["resp_code"] == "S"){
            //$this->EchoFormat("解绑成功！");
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
        }else if($RSignArray["resp_code"] =="F"){
            //$this->EchoFormat("解绑失败！");
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }


    }

    /**
     * 预支付接口
     * @return void
     */
    public function ReadyPay($param,$order){

        $AesKey = "4f66405c4f66405c";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $dgtl_envlp = "01|".$AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]

        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
//        var_dump($this->CER_FILE_PATH);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);
        $ProtocolNo = $param['protocol_no'];//签约协议号（确认绑卡返回）
        //$this->EchoFormat("签约协议号：".$ProtocolNo);
        $ProtocolNoAES = $this->AesEncrypt(base64_encode($ProtocolNo), $AesKey);//先BASE64后进行AES加密

        //$this->EchoFormat("签约协议号AES结果:".$ProtocolNoAES);


        $CardInfo="";//信用卡：信用卡有效期|安全码,借记卡：传空
//暂不支持信用卡
//CardInfo = $this->AesEncrypt(base64_encode($CardInfo), $AesKey);//先BASE64后进行AES加密

        $ReturnUrl="";//异步通知地址。

        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "05";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["trans_id"]=$param['trans_id'];//商户订单号
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["user_id"]= $param['user_id'];//用户在商户平台唯一ID
        $DateArry["protocol_no"]=$ProtocolNoAES;//签约协议号（密文）
        $DateArry["txn_amt"]= bcmul($param['txn_amt'],100);//交易金额 [单位：分  例：1元则提交100]，此处注意数据类型的转转，建议使用BigDecimal类弄进行转换为字串
        $DateArry["card_info"]= $CardInfo;//卡信息(信用卡：信用卡有效期)

        /**
         * -----------风控参数--------------
         * 本处只示例话费充值，商户根据自已的行业按照风控参数列表设置参数。
         *
         */
        /*--------风控基础参数------------- */
        $RiskItem = array();
        $RiskItem["goodsCategory"]="01";//商品类目 详见附录《商品类目》
        $RiskItem["userLoginId"]=$order['mobile'];//用户在商户系统中的登陆名（手机号、邮箱等标识）
        $RiskItem["userEmail"]="";
        $RiskItem["userMobile"]=$order['mobile'];//用户手机号
        $RiskItem["registerUserName"]=$order['cert_name'];//用户在商户系统中注册使用的名字
        $RiskItem["identifyState"]="1";//用户在平台是否已实名，1：是 ；0：不是
        $RiskItem["userIdNo"]=$order['cert_no'];//用户身份证号
        $RiskItem["registerTime"]=date('Y-m-dH:i:s',$order['create_time']);//格式为：YYYYMMDDHHMMSS
        $RiskItem["registerIp"]=getRealIp();//用户在商户端注册时留存的IP
        $RiskItem["chName"]=$order['cert_name'];//持卡人姓名
        $RiskItem["chIdNo"]="";//持卡人身份证号
        $RiskItem["chCardNo"]="";//持卡人银行卡号
        $RiskItem["chMobile"]="";//持卡人手机
        $RiskItem["chPayIp"]=getRealIp();//持卡人支付IP
        $RiskItem["deviceOrderNo"]="";//加载设备指纹中的订单号

        /**--------行业参数  (以下为游戏行业风控参，请参看接口文档附录风控参数)-------------**/
        $RiskItem["csName"]=$order['cert_name'];///收货人姓名
        $RiskItem["csMobile"]=$order['mobile'];///收货人手机
        $RiskItem["csIdType"]="00";//收货人证件类型
        $RiskItem["csIdNo"]=$order['cert_no'];
        $RiskItem["csProvince"]=$order['prov'];
        $RiskItem["csCity"]=$order['city'];//参见我司省份代码
        $RiskItem["csAddress"]=$order['address'];
        $RiskItem["prodNameList"]=$order['goods_title'].'部分租金';
        $RiskItem["prodTypeList"]='002';
        $RiskItem["prodQtyList"]='1';
        $RiskItem["prodAmtList"]=$param['txn_amt'];


        $DateArry["risk_item"]= json_encode($RiskItem);//加入风控参数(固定为JSON字串)
        $DateArry["return_url"]=$ReturnUrl;//最多填写三个地址,不同地址用间使用‘|’分隔


        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);
//    var_dump($RSignArray);

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        if(!$this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            throw new BaseException("获取验证码失败！");
        }
        self::requestLog("预支付接口",$DateArry,$RSignArray);


        if($RSignArray["resp_code"] == "S"){
            if(!array_key_exists("dgtl_envlp",$RSignArray)){
                throw new BaseException("缺少dgtl_envlp参数！");
            }
            if(!array_key_exists("unique_code",$RSignArray)){
                throw new BaseException("缺少unique_code参数！");
            }
            //$this->EchoFormat("dgtl_envlp:".$RSignArray["dgtl_envlp"]);
            $RDgtlEnvlp = $this->decryptByPFXFile($RSignArray["dgtl_envlp"], $this->PFX_FILE_PATH,$this->KEY_PWD);
            //$this->EchoFormat("返回数字信封：".$RDgtlEnvlp);
            $RAesKey=  CommonService::getAesKey($RDgtlEnvlp);//获取返回的AESkey
            //$this->EchoFormat("返回的AESkey:".$RAesKey);
            $UniqueCode=  base64_decode($this->AesDecrypt($RSignArray["unique_code"], $RAesKey));
            return $UniqueCode;
            //$this->EchoFormat("预支付唯一码:".$UniqueCode);
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
            $RDgtlEnvlp = $this->decryptByPFXFile($RSignArray["dgtl_envlp"], $this->PFX_FILE_PATH,$this->KEY_PWD);
            //$this->EchoFormat("返回数字信封：".$RDgtlEnvlp);
            $RAesKey=  CommonService::getAesKey($RDgtlEnvlp);//获取返回的AESkey
            //$this->EchoFormat("返回的AESkey:".$RAesKey);
            $UniqueCode=  base64_decode($this->AesDecrypt($RSignArray["unique_code"], $RAesKey));
            return $UniqueCode;
            throw new BaseException("处理中！");//异常不得做为订单状态。
        }else if($RSignArray["resp_code"] =="F"){
            //$this->EchoFormat("失败！");
            throw new BaseException($RSignArray['biz_resp_msg']);//异常不得做为订单状态。
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }
    }


    /**
     * 确认支付接口
     * @return void
     */
    public function ConfirmPay($param=[]){
        //$this->EchoFormat("==========================");
        //$this->EchoFormat("确认支付   测试实例");
        //$this->EchoFormat("==========================");
        $AesKey = "4f66405c4f66405c";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $dgtl_envlp = "01|".$AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]
        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
        //$this->EchoFormat("RSA数字信封：".$dgtl_envlp);

        $SMSStr=$param['sms_code'];//短信验证码，测试环境随机6位数;生产环境验证码预绑卡成功后发到用户手机。确认绑卡时回传。
        $UniqueCode = "{$param['protocol_no']}|".$SMSStr;//预支付唯一码(预绑卡返回的值)[格式：预签约唯一码|短信验证码]
        //$this->EchoFormat("UniqueCode：".$UniqueCode.",长度：".strlen($UniqueCode));
        $UniqueCodeAES = $this->AesEncrypt(base64_encode($UniqueCode), $AesKey);//先BASE64后进行AES加密
        //$this->EchoFormat("AES结果:".$UniqueCodeAES);

        $CardInfo="";//信用卡：信用卡有效期|安全码,借记卡：传空
//暂不支持信用卡
//$CardInfo = $this->AesEncrypt(base64_encode($CardInfo), $AesKey);//先BASE64后进行AES加密

        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "06";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["dgtl_envlp"]=$dgtl_envlp;


        $DateArry["unique_code"]= $UniqueCodeAES;//预支付唯一码
        $DateArry["card_info"]= $CardInfo;//卡信息


        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
//        $this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if(!$this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        self::requestLog("确认支付接口",$DateArry,$RSignArray);

        if($RSignArray["resp_code"] == "S"){
            //$this->EchoFormat("支付成功！[trans_id:".$RSignArray["trans_id"]."]");
            return $RSignArray;
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
            throw new BaseException("处理中！");//异常不得做为订单状态。

        }else if($RSignArray["resp_code"] =="F"){
            throw new BaseException($RSignArray["biz_resp_msg"]);//异常不得做为订单状态。
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }
    }


    /**
     * 订单查询接口
     * @return void
     */
    public function QueryOrder(){
        //$this->EchoFormat("==========================");
        //$this->EchoFormat("订单查询 测试实例");
        //$this->EchoFormat("==========================");

        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "07";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["orig_trans_id"]="TID16879351443055";//交易时的trans_id
        $DateArry["orig_trade_date"]= CommonService::getTime();//

        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
        //$this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if($this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            //$this->EchoFormat("验签:Yes");//验签成功
        }  else {
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

        if($RSignArray["resp_code"] == "S"){
            //$this->EchoFormat("支付成功！[trans_id:".$RSignArray["trans_id"]."]");
        }else if($RSignArray["resp_code"] == "I"){
            //$this->EchoFormat("处理中！");
        }else if($RSignArray["resp_code"] =="F"){
            //$this->EchoFormat("失败！");
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }
    }

    /**
     * 退款
     * @return void
     */
    public function refund($order){

        $DateArry = array();
        $ApiPostData=array();
        $DateArry["trans_id"]= $order["origMerchantOrderNo"];
        $DateArry["refund_order_no"]= $order['refundOrderNo'];//退款时商户端生成的订单号(每次请求不重复)
        $DateArry["refund_reason"]= $order['refundReason'];
        $DateArry["refund_amt"]=  $order["refundAmount"];//退款金额
        $DateArry["refund_time"]= date('YmdHis',time());//退款发起时间
        $DateArry["trans_serial_no"]= "RTSN"+strtotime(date('Y-m-d H:i:s',time()))+rand(1000,9999);//退款流水号(每次请求不重复)
        $DateArry["notice_url"]= '';//退款成功后通知地址。
        $DateArry["refund_type"]= 8;//1:网银、2:认证支付
        $DateArry["txn_sub_type"]= "09";//交易子类
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["member_id"]=$this->Member_Id;

        $ApiPostData["version"]=$this->Version;
        $ApiPostData["terminal_id"]= $this->Terminal_Id;
        $ApiPostData["txn_sub_type"]= "09";//交易子类
        $ApiPostData["member_id"]=$this->Member_Id;
        $ApiPostData["txn_type"]= "331";//交易类型
        $ApiPostData["data_type"]= "json";//交易类型

        $Encrypted_string = str_replace("\\/", "/",json_encode($DateArry));//转JSON


        $Encrypted = $this->encryptedByPrivateKey($Encrypted_string,$this->PFX_FILE_PATH,$this->KEY_PWD);//先BASE64进行编码再RSA加密
        $ApiPostData["data_content"]=$Encrypted;


        $request_url = "https://public.baofoo.com/cutpayment/api/backTransRequest";//请求宝付地址
        $PostString  = $this->Post($ApiPostData, $request_url);
//        $this->EchoFormat("请求返回:".$PostString);
//        dd($PostString);
        if(empty($PostString)){
            throw new BaseException("返回异常！");
        }

        $Result=$this->decryptByPublicKey($PostString);
        $Result=json_decode($Result,true);
        if($Result["resp_code"] == "0000"){
            return true;
            //$this->EchoFormat("支付成功！[trans_id:".$RSignArray["trans_id"]."]");
        }else{
            throw new BaseException($Result['resp_msg']);//异常不得做为订单状态。
        }
    }

    /**
     * 直接支付
     * @return void
     */
    public function SinglePay($param=[],$order){

        $AesKey = "4f66405c4f66405c";//商户自定义（可随机生成  商户自定义(AES key长度为=16位)）
        $dgtl_envlp = "01|".$AesKey;//使用接收方的公钥加密后的对称密钥，并做Base64转码，明文01|对称密钥，01代表AES[密码商户自定义]
//        var_dump($this->CER_FILE_PATH);

        //$this->EchoFormat("密码dgtl_envlp：".$dgtl_envlp);
        $dgtl_envlp = $this->encryptByCERFile($dgtl_envlp, $this->CER_FILE_PATH);//公钥加密
//      $this->EchoFormat("RSA数字信封：".$dgtl_envlp);
        $ProtocolNo = $param['protocol_no'];//签约协议号（确认绑卡返回）
        //$this->EchoFormat("签约协议号：".$ProtocolNo);
        $ProtocolNoAES = $this->AesEncrypt(base64_encode($ProtocolNo), $AesKey);//先BASE64后进行AES加密

        //$this->EchoFormat("签约协议号AES结果:".$ProtocolNoAES);


        $CardInfo="";//信用卡：信用卡有效期|安全码,借记卡：传空
//暂不支持信用卡
//CardInfo = $this->AesEncrypt(base64_encode($CardInfo), $AesKey);//先BASE64后进行AES加密

        $ReturnUrl="";//异步通知地址。

        $DateArry = array();
        $DateArry["send_time"]=CommonService::getTime();
        $DateArry["msg_id"]="TISN".CommonService::getTransid().CommonService::getRand4();//报文流水号
        $DateArry["version"]=$this->Version;
        $DateArry["terminal_id"]= $this->Terminal_Id;
        $DateArry["txn_type"]= "08";//交易类型
        $DateArry["member_id"]=$this->Member_Id;
        $DateArry["trans_id"]=$param['trans_id'];//商户订单号
        $DateArry["dgtl_envlp"]=$dgtl_envlp;
        $DateArry["user_id"]= $param['user_id'];//用户在商户平台唯一ID
        $DateArry["protocol_no"]=$ProtocolNoAES;//签约协议号（密文）
        $DateArry["txn_amt"]= bcmul($param['txn_amt'],100);//交易金额 [单位：分  例：1元则提交100]，此处注意数据类型的转转，建议使用BigDecimal类弄进行转换为字串
        $DateArry["card_info"]= $CardInfo;//卡信息(信用卡：信用卡有效期)

        /**
         * -----------风控参数--------------
         * 本处只示例话费充值，商户根据自已的行业按照风控参数列表设置参数。
         *
         */
        /*--------风控基础参数------------- */
        $RiskItem = array();
        $RiskItem["goodsCategory"]="01";//商品类目 详见附录《商品类目》
        $RiskItem["userLoginId"]=$order['mobile'];//用户在商户系统中的登陆名（手机号、邮箱等标识）
        $RiskItem["userEmail"]="";
        $RiskItem["userMobile"]=$order['mobile'];//用户手机号
        $RiskItem["registerUserName"]=$order['cert_name'];//用户在商户系统中注册使用的名字
        $RiskItem["identifyState"]="1";//用户在平台是否已实名，1：是 ；0：不是
        $RiskItem["userIdNo"]=$order['cert_no'];//用户身份证号
        $RiskItem["registerTime"]=date('Y-m-dH:i:s',$order['create_time']);//格式为：YYYYMMDDHHMMSS
        $RiskItem["registerIp"]=getRealIp();//用户在商户端注册时留存的IP
        $RiskItem["chName"]=$order['cert_name'];//持卡人姓名
        $RiskItem["chIdNo"]="";//持卡人身份证号
        $RiskItem["chCardNo"]="";//持卡人银行卡号
        $RiskItem["chMobile"]="";//持卡人手机
        $RiskItem["chPayIp"]=getRealIp();//持卡人支付IP
        $RiskItem["deviceOrderNo"]="";//加载设备指纹中的订单号

        /**--------行业参数  (以下为游戏行业风控参，请参看接口文档附录风控参数)-------------**/
        $RiskItem["csName"]=$order['cert_name'];///收货人姓名
        $RiskItem["csMobile"]=$order['mobile'];///收货人手机
        $RiskItem["csIdType"]="00";//收货人证件类型
        $RiskItem["csIdNo"]=$order['cert_no'];
        $RiskItem["csProvince"]=$order['prov'];
        $RiskItem["csCity"]=$order['city'];//参见我司省份代码
        $RiskItem["csAddress"]=$order['address'];
        $RiskItem["prodNameList"]=$order['goods_title'].'部分租金';
        $RiskItem["prodTypeList"]='002';
        $RiskItem["prodQtyList"]='1';
        $RiskItem["prodAmtList"]=$param['txn_amt'];


        $DateArry["risk_item"]= json_encode($RiskItem);//加入风控参数(固定为JSON字串)
        $DateArry["return_url"]=$ReturnUrl;//最多填写三个地址,不同地址用间使用‘|’分隔


        //$this->EchoFormat("报文流水号:".$DateArry["msg_id"]);
        $SignVStr =  CommonService::SortAndOutString($DateArry);//签名字段格式化
        //$this->EchoFormat("SHA-1摘要明文字串：".$SignVStr);
        $SHA1Sign = $this->Sha1AndHex(urldecode($SignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("SHA-1摘要结果：".$SHA1Sign);

        $Sign = $this->Sign($SHA1Sign, $this->PFX_FILE_PATH,$this->KEY_PWD);
        //$this->EchoFormat("RSA签名结果：".$Sign);
        $DateArry["signature"]=$Sign;//签名域

        $PostString  = $this->Post($DateArry, $this->POST_URL);
//        $this->EchoFormat("请求返回:".$PostString);

        IF(empty($PostString)){
            throw new BaseException("返回异常！");
        }
        parse_str($PostString,$ReturnData);//参数解析

        if(!array_key_exists("signature",$ReturnData)){
            throw new BaseException("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);
        //$this->EchoFormat("返回SHA-1摘要字串：".urldecode($RSignVStr));

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)
        //$this->EchoFormat("返回SHA-1摘要结果：".$RSignature);

        if(!$this->VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            throw new BaseException("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new BaseException("缺少resp_code参数！");
        }

//        var_dump($RSignArray);
        if($RSignArray["resp_code"] == "S"){
            //$this->EchoFormat("支付成功！[trans_id:".$RSignArray["trans_id"]."]");
            return ['status'=>1,'trans_id'=>$RSignArray["trans_id"]];
        }else if($RSignArray["resp_code"] == "I"){
            return ['status'=>2];
        }else if($RSignArray["resp_code"] =="F"){
            return ['status'=>3];
        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }
    }


    /**
     * 接收异步通知
     */
    public function returnUrl($ReturnData){
//        Log::LogWirte("接收参数：".http_build_query($_REQUEST));
        if(!array_key_exists("signature",$ReturnData)){
            throw new Exception("缺少验签参数！");
        }
        $RSign=$ReturnData["signature"];//存储返回签名做后续验签使用。
        $RSignArray = CommonService::array_remove($ReturnData, "signature");//需要删除签名字段

        $RSignVStr =CommonService::SortAndOutString($RSignArray);

        $RSignature = $this->Sha1AndHex(urldecode($RSignVStr));//签名(注意此处urldecode方法主要是去除send_time中间的空格和符号的自动自urlencode)

        if(!SignatureUtils::VerifySign($RSignature,$this->CER_FILE_PATH,$RSign)){
            throw new Exception("验签失败！");
        }

        if(!array_key_exists("resp_code",$RSignArray)){
            throw new Exception("缺少resp_code参数！");
        }

        if($RSignArray["resp_code"] == "S"){
            return $RSignArray;
        }else if($RSignArray["resp_code"] == "I"){
            throw new BaseException("处理中！");//异常不得做为订单状态。
        }else if($RSignArray["resp_code"] =="F"){
            throw new BaseException("失败！");//异常不得做为订单状态。

        }else{
            throw new BaseException("反回异常！");//异常不得做为订单状态。
        }
    }
    public  function EchoFormat($Astring){
        $LogTime = date('Y-m-d H:i:s',time());
        echo $LogTime." ".$Astring."<br>";
    }

    /**
     *
     * @param type $data    待加密的数据
     * @param type $key     密钥
     * @param type $iv      密钥
     * @return type
     * @throws BaseException
     */
    public  function AesEncrypt($data,$key){
        if (!function_exists( 'bin2hex')) {
            function hex2bin( $str ) {
                $sbin = "";
                $len = strlen( $str );
                for ( $i = 0; $i < $len; $i += 2 ) {
                    $sbin .= pack( "H*", substr( $str, $i, 2 ) );
                }
                return $sbin;
            }
        }
        if(!(strlen($key) == 16)){
            throw new BaseException("AES密码长度固定为16位！当前KEY长度为：".  strlen($key));
        }
        $iv=$key;//偏移量与key相同
        //OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING
        $encrypted = openssl_encrypt($data, "AES-128-CBC", $key,OPENSSL_RAW_DATA,$iv);
        //$encrypted=mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_CBC,$iv);
        $data=bin2hex($encrypted);
        return $data;
    }
    /**
     * 解密
     * @param type $sData   待解密的数据
     * @param type $sKey    密钥
     * @param type $iv      密钥
     * @return type
     * @throws BaseException
     */
    public  function AesDecrypt($sData,$sKey){
        if(!(strlen($sKey) == 16)){
            throw new BaseException("AES密码长度固定为16位！当前KEY长度为：".  strlen($sKey));
        }
        $sIv=$sKey;//偏移量与key相同
        $sData=hex2bin($sData);
        $retrun = openssl_decrypt($sData, "AES-128-CBC",$sKey,OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,$sIv);
        return $retrun;
    }


    /**
     * 读取私钥
     * @param type $PfxPath
     * @param type $PrivateKPASS
     * @return array
     * @throws BaseException
     */
    private static function  getPriveKey($PfxPath,$PrivateKPASS){
        try {
            if(!file_exists($PfxPath)) {
                throw new BaseException("私钥文件不存在！路径：".$PfxPath);
            }
            $PKCS12 = file_get_contents($PfxPath);
            $PrivateKey = array();
            if(openssl_pkcs12_read($PKCS12, $PrivateKey, $PrivateKPASS)){
                return $PrivateKey["pkey"];
            }else{
                throw new BaseException("私钥证书读取出错！原因[证书或密码不匹配]，请检查本地证书相关信息。");
            }
        } catch (BaseException $ex) {
            $ex->getTrace();
        }
    }

    /**
     * 读取公钥
     * @param type $PublicPath
     * @return type
     * @throws BaseException
     */
    private static function  getPublicKey($PublicPath){
        try {
            if(!file_exists($PublicPath)) {
                throw new BaseException("公钥文件不存在！路径：".$PublicPath);
            }
            $KeyFile = file_get_contents($PublicPath);
            $PublicKey = openssl_get_publickey($KeyFile);
            if(empty($PublicKey)){
                throw new BaseException("公钥不可用！路径：".$PublicPath);
            }
            return $PublicKey;
        } catch (BaseException $ex) {
            $ex->getTraceAsString();
        }
    }

    /**
     * 公钥加密
     * @param type $Data    加密数据
     * @param type $PfxPath     私钥路径
     * @param type $PrivateKPASS  私钥密码
     * @return type
     * @throws BaseException
     */
    public static function encryptByCERFile($Data,$PublicPath){
        try {
            if (!function_exists( 'bin2hex')) {
                throw new BaseException("bin2hex PHP5.4及以上版本支持此函数，也可自行实现！");
            }
            $KeyObj = self::getPublicKey($PublicPath);
            $BASE64EN_DATA = base64_encode($Data);
            $EncryptStr = "";
            $blockSize = self::get_Key_Size($KeyObj,false);
            if($blockSize<=0){
                throw new BaseException("BlockSize is 0");
            }else{
                $blockSize = $blockSize/8-11;
            }
            $totalLen = strlen($BASE64EN_DATA);
            $EncryptSubStarLen = 0;
            $EncryptTempData="";
            while ($EncryptSubStarLen < $totalLen){
                openssl_public_encrypt(substr($BASE64EN_DATA, $EncryptSubStarLen, $blockSize), $EncryptTempData, $KeyObj);
                $EncryptStr .= bin2hex($EncryptTempData);
                $EncryptSubStarLen += $blockSize;
            }
            return $EncryptStr;
        } catch (BaseException $exc) {
            echo $exc->getTraceAsString();
        }
    }

    public   function encryptedByPrivateKey($data_content,$PfxPath,$PrivateKPASS){
        $data_content = base64_encode($data_content);
        $encrypted = "";
        $totalLen = strlen($data_content);
        $encryptPos = 0;
        $KeyObj = self::getPriveKey($PfxPath,$PrivateKPASS);

        while ($encryptPos < $totalLen){
            openssl_private_encrypt(substr($data_content, $encryptPos, (16*8-11)), $encryptData, $KeyObj);
            $encrypted .= bin2hex($encryptData);
            $encryptPos += (16*8-11);
        }
        return $encrypted;
    }

    /**
     * 私钥加密
     * @param type $Data
     * @param type $PfxPath
     * @param type $PrivateKPASS
     * @return type
     * @throws BaseException
     */
    public static function encryptByPFXFile($Data,$PfxPath,$PrivateKPASS){
        try {
            if (!function_exists( 'bin2hex')) {
                throw new BaseException("bin2hex PHP5.4及以上版本支持此函数，也可自行实现！");
            }
            $KeyObj = self::getPriveKey($PfxPath,$PrivateKPASS);
            $BASE64EN_DATA = base64_encode($Data);
            $EncryptStr = "";
            $blockSize = self::get_Key_Size($KeyObj);
            if($blockSize<=0){
                throw new BaseException("BlockSize is 0");
            }else{
                $blockSize = $blockSize/8-11;//分段
            }
            $totalLen = strlen($BASE64EN_DATA);
            $EncryptSubStarLen = 0;
            $EncryptTempData="";
            while ($EncryptSubStarLen < $totalLen){
                openssl_private_encrypt(substr($BASE64EN_DATA, $EncryptSubStarLen, $blockSize), $EncryptTempData, $KeyObj);
                $EncryptStr .= bin2hex($EncryptTempData);
                $EncryptSubStarLen += $blockSize;
            }
            return $EncryptStr;
        } catch (BaseException $exc) {
            echo $exc->getTraceAsString();
        }
    }

    /**
     * 私钥解密
     * @param type $Data    解密数据
     * @param type $PublicPath  解密公钥路径
     * @return type
     * @throws BaseException
     */
    public static function decryptByPFXFile($Data,$PfxPath,$PrivateKPASS){
        try {
            if (!function_exists( 'hex2bin')) {
                throw new BaseException("hex2bin PHP5.4及以上版本支持此函数，也可自行实现！");
            }
            $KeyObj = self::getPriveKey($PfxPath,$PrivateKPASS);
            $blockSize = self::get_Key_Size($KeyObj);
            if($blockSize<=0){
                throw new BaseException("BlockSize is 0");
            }else{
                $blockSize = $blockSize/4;
            }
            $DecryptRsult="";
            $totalLen = strlen($Data);
            $EncryptSubStarLen = 0;
            $DecryptTempData="";
            while ($EncryptSubStarLen < $totalLen) {
                openssl_private_decrypt(hex2bin(substr($Data, $EncryptSubStarLen, $blockSize)), $DecryptTempData, $KeyObj);
                $DecryptRsult .= $DecryptTempData;
                $EncryptSubStarLen += $blockSize;
            }
            return base64_decode($DecryptRsult);
        } catch (BaseException $exc) {
            echo $exc->getTraceAsString();
        }
    }

    /**
     * 公钥解密
     * @param type $Data
     * @param type $PublicPath
     * @return type
     * @throws BaseException
     */
    public static function decryptByCERFile($Data,$PublicPath) {
        try {
            if (!function_exists( 'hex2bin')) {
                throw new BaseException("hex2bin PHP5.4及以上版本支持此函数，也可自行实现！");
            }
            $KeyObj = self::getPublicKey($PublicPath);
            $DecryptRsult="";
            $blockSize = self::get_Key_Size($KeyObj,false);
            if($blockSize<=0){
                throw new BaseException("BlockSize is 0");
            }else{
                $blockSize = $blockSize/4;
            }
            $totalLen = strlen($Data);
            $EncryptSubStarLen = 0;
            $DecryptTempData="";
            while ($EncryptSubStarLen < $totalLen) {
                openssl_public_decrypt(hex2bin(substr($Data, $EncryptSubStarLen, $blockSize)), $DecryptTempData, $KeyObj);
                $DecryptRsult .= $DecryptTempData;
                $EncryptSubStarLen += $blockSize;
            }
            return base64_decode($DecryptRsult);
        } catch (BaseException $exc) {
            echo $exc->getTraceAsString();
        }
    }

    /**
     * 获取证书长度
     * @param type $Key_String
     * @param type $Key_Type
     * @return int
     * @throws BaseException
     */
    private static function get_Key_Size($Key_String,$Key_Type=true){
        $Key_Temp=array();
        try{
            if($Key_Type){//私钥
                $Key_Temp = openssl_pkey_get_details(openssl_pkey_get_private($Key_String));
            }else if(openssl_pkey_get_public($Key_String)){//公钥
                $Key_Temp = openssl_pkey_get_details(openssl_pkey_get_public($Key_String));
            }else{
                throw new BaseException("Is not a key");
            }
            IF(array_key_exists("bits",$Key_Temp)){
                return $Key_Temp["bits"];
            }else{
                return 0;
            }
        } catch (BaseException $ex){
            $ex->getTrace();
            return 0;
        }
    }

    /**
     *
     * @param type $Data  原数据
     * @param type $PfxPath 私钥路径
     * @param type $Pwd 私钥密码
     * @return type
     * @throws BaseException
     * @author 大圣 <dasheng@baofu.com>
     */
    public static function Sign($Data,$PfxPath,$Pwd)
    {

        if (!function_exists( 'bin2hex')) {
            function hex2bin( $str ) {
                $sbin = "";
                $len = strlen( $str );
                for ( $i = 0; $i < $len; $i += 2 ) {
                    $sbin .= pack( "H*", substr( $str, $i, 2 ) );
                }
                return $sbin;
            }
        }
        if(!file_exists($PfxPath)) {
            throw new BaseException("私钥文件不存在！");
        }

        $pkcs12 = file_get_contents($PfxPath);
        $PfxPathStr=array();
        if (openssl_pkcs12_read($pkcs12, $PfxPathStr, $Pwd)) {
            $PrivateKey = $PfxPathStr['pkey'];
            $BinarySignature=NULL;
            if (openssl_sign($Data, $BinarySignature, $PrivateKey, OPENSSL_ALGO_SHA1)) {
                return bin2hex($BinarySignature);
            } else {
                throw new BaseException("加签异常！");
            }
        } else {
            throw new BaseException("私钥读取异常【密码和证书不匹配】！");
        }
    }

    /**
     * 验证签名自己生成的是否正确
     *
     * @param string $Data 签名的原文
     * @param string $CerPath  公钥路径
     * @param string $SignaTure 签名
     * @return bool
     * @author 大圣 <dasheng@baofu.com>
     */
    public static function VerifySign($Data,$CerPath,$SignaTure)
    {
        if (!function_exists( 'hex2bin')) {
            function hex2bin( $str ) {
                $sbin = "";
                $len = strlen( $str );
                for ( $i = 0; $i < $len; $i += 2 ) {
                    $sbin .= pack( "H*", substr( $str, $i, 2 ) );
                }
                return $sbin;
            }
        }
        if(!file_exists($CerPath)) {
            throw new BaseException("公钥文件不存在！路径：".$CerPath);
        }
        $PubKey = file_get_contents($CerPath);
        $Certs = openssl_get_publickey($PubKey);
        $ok = openssl_verify($Data,hex2bin($SignaTure), $Certs);
        if ($ok == 1) {
            return true;
        }
        return false;
    }

    // 公钥解密
    public  function decryptByPublicKey($encrypted){
        $decrypt = "";
        $totalLen = strlen($encrypted);
        $decryptPos = 0;
        $keyFile = file_get_contents($this->CER_FILE_PATH);
        $this->public_key = openssl_get_publickey($keyFile);

        while ($decryptPos < $totalLen) {
            openssl_public_decrypt(hex2bin(substr($encrypted, $decryptPos, 16 * 16)), $decryptData, $this->public_key);
            $decrypt .= $decryptData;
            $decryptPos += 16 * 16;
        }
        //openssl_public_decrypt($encrypted, $decryptData, $this->public_key);
        $decrypt=base64_decode($decrypt);
        return $decrypt;
    }
    /**
     * SHA1摘要
     * @param type $Strings
     * @return type
     */
    public static function Sha1AndHex($Strings){
        return openssl_digest($Strings, "SHA1");
    }
    public static function Post($PostArry,$Req_Url){
        try {
            $postData = $PostArry;
            $postDataString = http_build_query($postData);//格式化参数
//            self::EchoFormat("发送参数：".$Req_Url."?".$postDataString);
            $curl = curl_init(); // 启动一个CURL会话
            curl_setopt($curl, CURLOPT_URL, $Req_Url); // 要访问的地址
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // 对认证证书来源的检查
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); // 从证书中检查SSL加密算法是否存在
            //curl_setopt($curl, CURLOPT_SSLVERSION, 6); //CURL_SSLVERSION_DEFAULT (0), CURL_SSLVERSION_TLSv1 (1), CURL_SSLVERSION_SSLv2 (2), CURL_SSLVERSION_SSLv3 (3), CURL_SSLVERSION_TLSv1_0 (4), CURL_SSLVERSION_TLSv1_1 (5)， CURL_SSLVERSION_TLSv1_2 (6) 中的其中一个。
            curl_setopt($curl, CURLOPT_POST, true); //发送一个常规的Post请求
            curl_setopt($curl, CURLOPT_POSTFIELDS, $postDataString); // Post提交的数据包
            curl_setopt($curl, CURLOPT_TIMEOUT, 60); // 设置超时限制防止死循环返回
            curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
            $tmpInfo = curl_exec($curl); // 执行操作
            if (curl_errno($curl)) {
                $tmpInfo = curl_error($curl);//捕抓异常
            }
            curl_close($curl); // 关闭CURL会话
            return $tmpInfo; // 返回数据
        } catch (BaseException $ex) {
            echo $ex->getTraceAsString();
        }
    }


}
